package cn.czh.basic.service.impl;

import cn.czh.basic.constant.VerifyCodeConstant;
import cn.czh.basic.dto.SmsDto;
import cn.czh.basic.exception.BusinessException;
import cn.czh.basic.service.IVerifyCodeService;

import cn.czh.basic.util.StrUtils;
import cn.czh.basic.util.VerifyCodeUtils;
import cn.czh.user.domain.User;
import cn.czh.user.mapper.UserMapper;
import com.baomidou.mybatisplus.generator.config.IFileCreate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.sql.Struct;
import java.util.concurrent.TimeUnit;
@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public String getImgCode(String key) {
        //1.获取随机验证码
        String code = StrUtils.getComplexRandomString(4);
        //2.保存到redis -- 并设置过期时间5分钟
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        //3.获取图形验证码编码之后的字符串
        String base64Str = VerifyCodeUtils.verifyCode(115, 40, code);
        return base64Str;
    }

    @Override
    public void smsCode(SmsDto smsDto) {
        String phone = smsDto.getPhone();
        String imageCode = smsDto.getImageCode();
        String imageCodeKey = smsDto.getImageCodeKey();
        //1.校验
        //1.1非空校验 - 3个
        //校验手机号
        if (StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号不能空,请输入手机号");
        }
        //校验用户是否输入图形验证码
        if (StringUtils.isEmpty(imageCode)){
            throw new BusinessException("请输入图形验证码");
        }
        //校验是否获取redis的图形验证码
        if (StringUtils.isEmpty(imageCodeKey)){
            throw new BusinessException("请重新获取图形验证码");
        }

        //1.2判断该手机用户是否已经注册
        User user = userMapper.loadByPhone(phone);
        if (user != null){
            throw new BusinessException("该手机号已经注册,请直接登录");
        }

        //1.3校验图形验证码是否过期
        Object obj = redisTemplate.opsForValue().get(imageCodeKey);
        if (obj==null){ //如果为空说明已经过期
            throw new BusinessException("图形验证码已过期,请重新获取");
        }
        //1.4校验图形验证码是否正确
        if (!obj.toString().equalsIgnoreCase(imageCode)){
            throw new BusinessException("图形验证码错误");
        }

        //2.生成手机验证码 - redis保存手机验证码 register:13438028809 - 6969:172236599456(时间戳)
        //2.1从redis中获取手机验证码 - 进行判断
        Object smsObj = redisTemplate.opsForValue().get(VerifyCodeConstant.REGISTER_CODE_PREFIX +phone); //register:13438028809
        String smsCode = null;
        if (smsObj == null){
            //2.1.1如果redis中没有说明是第一次获取或者手机验证码已经过期 ——>重新调用StrUtils工具类生成随机手机验证码
            smsCode = StrUtils.getRandomString(6);
        }else {
            //2.1.2如果redis中有说明手机验证码没有过期 —— 判断重发时间【当前时间戳-旧时间戳与1分钟做比较】
            long nowTime = System.currentTimeMillis(); //当前时间戳
            String oldTimeTemp = smsObj.toString().split(":")[1]; //获得旧时间戳 -- 字符串
            long oldTime = Long.parseLong(oldTimeTemp); //进行强转变为整数类型
            if ((nowTime-oldTime)<1*60*1000){ //重复发送短信验证码
                //2.1.2.1如果没有过重复时间 -- 抛出异常【操作频繁,请稍后再试】
                throw new BusinessException("请勿重复发送验证码,请稍后重试");
            }else {
                //2.1.2.2如果过了重发时间 -- 就使用以前的验证码
                smsCode = smsObj.toString().split(":")[0];
            }
        }


        //4.手机验证码保存到redis -重新设置过期时间3分钟
        redisTemplate.opsForValue().set(VerifyCodeConstant.REGISTER_CODE_PREFIX+ phone, smsCode+":"+System.currentTimeMillis(),
                3,TimeUnit.MINUTES);

        //5.调用工具类发送短信
       // SmsUtils.sendSms(phone,"你的验证码是：" + smsCode + "请在3分钟内使用");
        System.out.println("你的验证码是：" + smsCode + ",请在3分钟内使用");

    }

    @Override
    public void binderSmsCode(SmsDto smsDto) {
        String phone = smsDto.getPhone();
        //1.校验非空
        if (StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号不能为空");
        }
        //2.生成手机验证码
        //redis保存手机验证码
        //2.1从redis中获取手机验证码 - 进行判断
        Object smsObj = redisTemplate.opsForValue().get(VerifyCodeConstant.BINDER_CODE_PREFIX+phone);
        String smsCode = null;
        if (smsObj == null){
            //如果没有 = 第一次获取或手机验证码过期 -> 重新调用StrUtils创建新的手机验证码
            smsCode = StrUtils.getComplexRandomString(6);
        }else {
            //如果有 = 手机验证码过期没有过期 -> 判断重发时间【时间戳相减与1分钟】
            long nowTime = System.currentTimeMillis();
            String oldTimeTemp = smsObj.toString().split(":")[1];
            long oldTime = Long.parseLong(oldTimeTemp);
            if((nowTime-oldTime)<1*60*1000){//重复发送短信验证码
                //a21.如果没有过重发时间 -> 抛业务异常【操作过于频繁，请稍后再试】
                throw new BusinessException("操作频繁，请稍后再试");
            }else{
                //a22.如果过了重发时间 -> 就使用以前的验证码
                smsCode = smsObj.toString().split(":")[0];
            }
        }
        //手机验证码保存到redis - 要不要刷新过期时间？[保存到redis要不要再次设置3分钟有效]
        redisTemplate.opsForValue().set(VerifyCodeConstant.BINDER_CODE_PREFIX+phone,
                smsCode+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);
        //调用工具类发送短信
        //SmsUtils.sendSms(phone,"你的验证码是：" + smsCode+",请在3分钟内使用!!!");
        System.out.println("你的验证码是：" + smsCode+",请在3分钟内使用!!!");
    }
}
